package com.reflect;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.io.BufferedInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author CKC
 * &#064;date  2023/4/27 19:05
 */
public class TEST {

    private static final Calendar CAL = Calendar.getInstance();

    private static final String[] VAL = {"主  ", "白  ", "副  ", "夜  ", "核 酸", "下 副", "休  "};

    private static final String URL = "https://timor.tech/api/holiday/year/";

    private static final String[] PERSON_NAME = {"陈奇钰", "熊 洋", "孙 华", "文 丽", "陈佳丽", "徐若玉", "苏春玲"};

    private static int year() {
        return CAL.get(Calendar.YEAR);
    }

    private static int maxDay() {
        return CAL.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    private static int month() {
        CAL.add(Calendar.MONTH, 1);
        return CAL.get(Calendar.MONTH) + 1;
    }

    public static void main(String[] args) {
        int month = month();
        int day = maxDay();
        int year = year();
        //int holiday = getHoliday(year, month) + 6;//总共的假期天数
        int holiday = 3 + 6;//总共的假期天数
        System.out.println(year + "年" + month + "月" + "共有" + day + "天" + ",休假天数：" + holiday);

        String[][] work = new String[7][day];
        System.out.println("生成每天必须的(主、白、副、夜) 四个班中......");

        for (int i = 0; i < day; i++) {
            randomZhuBaiFuYe(work, i);
        }

        theConditionsAreMet(work, true);
        System.out.println("生成完成...");
        println(work);

        System.out.println();
        System.out.println();
        System.out.println();
        //insertXiaFu(work);
        //println(work);

        System.out.println("本月添加休息时间中....");
        insertHoliday(work, holiday);
        System.out.println("本月添加休息时间完成.......");
        println(work);


        //println(work);
    }

    private static void insertXiaFu(String[][] work) {
        int rows = work.length;
        int width = work[0].length;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < width; j++) {
                if (work[i][j] == null) {
                    if (j == 0) {
                        continue;
                    }
                    if ("夜  ".equals(work[i][j - 1])) {
                        work[i][j] = VAL[5];
                    }
                }
            }
        }

    }

    private static void insertHoliday(String[][] work, int holidays) {
        ArrayList<List<Integer>> list = new ArrayList<>();
        for (String[] rows : work) {
            ArrayList<Integer> integers = new ArrayList<>();
            for (int i = 0; i < rows.length; i++) {
                if (rows[i] == null) {
                    integers.add(i);
                }
            }
            list.add(integers);
        }

        for (int i = 0; i < list.size(); i++) {
            List<Integer> personYue = list.get(i);
            if (personYue.size() < holidays) {
                System.err.println(PERSON_NAME[i] + "的假期，在本月不能调休完。请人工进行本次排班。");
                System.exit(-1);
            }
            Collections.shuffle(personYue);
            Collections.shuffle(personYue);
            personYue = personYue.subList(0, holidays);
            int finalI = i;
            personYue.forEach(holiday1 -> work[finalI][holiday1] = VAL[6]);
        }


    }

    private static void println(String[][] print) {
        int rows = print.length;
        int width = print[0].length;
        List<String> tmp = Arrays.asList(VAL);
        int[][] statistics = new int[7][7];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < width; j++) {
                String s = print[i][j];
                int i1 = tmp.indexOf(s);
                if (VAL[0].equals(s)) {
                    statistics[i][i1]++;
                }
                if (VAL[1].equals(s)) {
                    statistics[i][i1]++;
                }
                if (VAL[2].equals(s)) {
                    statistics[i][i1]++;
                }
                if (VAL[3].equals(s)) {
                    statistics[i][i1]++;
                }
                if (VAL[4].equals(s)) {
                    statistics[i][i1]++;
                }
                if (VAL[5].equals(s)) {
                    statistics[i][i1]++;
                }
                if (VAL[6].equals(s)) {
                    statistics[i][i1]++;
                }
            }
        }


        System.out.print("\t\t");
        for (int i = 0; i < width; i++) {
            System.out.print((i + 1) + "    \t");
        }

        Arrays.stream(VAL).forEach(str -> System.out.print(str + " \t"));
        System.out.println();
        for (int i = 0; i < rows; i++) {
            System.out.print(PERSON_NAME[i] + ":\t");
            for (int j = 0; j < width; j++) {
                if (print[i][j] == null) {
                    System.out.print("___ " + "\t");
                } else {
                    System.out.print(print[i][j] + "\t");
                }
            }
            Arrays.stream(statistics[i]).forEach(num -> System.out.print(num + "    \t"));
            System.out.println();
        }
    }

    private static void randomZhuBaiFuYe(String[][] work, int day) {
        while (true) {
            List<Integer> list = Arrays.asList(0, 1, 2, 3); //主、白、副、夜
            Collections.shuffle(list);
            List<Integer> person = Arrays.asList(0, 1, 2, 3, 4, 5, 6);
            Collections.shuffle(person);
            boolean flag = false;
            int dayTmp = day == 0 ? day : day - 1;
            for (int i = 0; i < list.size(); i++) {
                Integer integer = person.get(i);
                Integer banType = list.get(i);
                if (banType == 0) {  //当前班是主班  前一天不能是主班
                    if (VAL[0].equals(work[integer][dayTmp])) {
                        if (day != 0) {
                            flag = true;

                        }
                    }
                }
                if (banType == 0 || banType == 1) { //当前插入的是 白、主班 前一天不能是夜班
                    if (VAL[3].equals(work[integer][dayTmp])) {
                        flag = true;

                    }
                }

                if (banType == 2) { // 副 前一天必须是夜班
                    if (day != 0 && !VAL[3].equals(work[integer][dayTmp])) {
                        flag = true;

                    }
                }

                if (banType == 3) { //夜班  前一天不能也是夜班
                    if (VAL[3].equals(work[integer][dayTmp])) {
                        flag = true;

                    }
                }
                work[integer][day] = VAL[banType];
            }
            boolean met = theConditionsAreMet(work, false);
            if (met && !flag) {
                break;
            }
            for (int i = 0; i < 7; i++) {
                work[i][day] = null;
            }
        }
    }

    private static boolean theConditionsAreMet(String[][] work, boolean flag) {
        List<Integer> list = new LinkedList<>();
        List<Integer> zhu = new ArrayList<>();
        List<Integer> ye = new LinkedList<>();
        List<Integer> bai = new ArrayList<>();
        List<Integer> fu = new ArrayList<>();
        for (String[] person : work) {
            int workDays = 0;
            int workDayYe = 0;
            int workDayZhu = 0;
            int workDayBai = 0;
            int workDayFu = 0;
            for (String dayWork : person) {
                if (dayWork != null) {
                    workDays++;
                }
                if (VAL[0].equals(dayWork)) {
                    workDayZhu++;
                }
                if (VAL[1].equals(dayWork)) {
                    workDayBai++;
                }
                if (VAL[2].equals(dayWork)) {
                    workDayFu++;
                }
                if (VAL[3].equals(dayWork)) {
                    workDayYe++;
                }
            }
            list.add(workDays);
            zhu.add(workDayZhu);
            bai.add(workDayBai);
            fu.add(workDayFu);
            ye.add(workDayYe);
        }
        List<Integer> collect = list.stream().sorted().collect(Collectors.toList());
        Integer first = collect.get(0);
        Integer last = collect.get(collect.size() - 1);
        int i = last - first;
        if (i > 2) {
            return false;
        }

        List<Integer> yeList = ye.stream().sorted().collect(Collectors.toList());
        Integer first1 = yeList.get(0);
        Integer last1 = yeList.get(collect.size() - 1);
        int i1 = last1 - first1;
        if (i1 > 2) {
            return false;
        }

        List<Integer> zhuList = zhu.stream().sorted().collect(Collectors.toList());
        Integer zhu1 = zhuList.get(0);
        Integer zhu2 = zhuList.get(collect.size() - 1);
        int i2 = zhu2 - zhu1;
        if (i2 > 2) {
            return false;
        }

        List<Integer> baiList = bai.stream().sorted().collect(Collectors.toList());
        Integer bai1 = baiList.get(0);
        Integer bai2 = baiList.get(collect.size() - 1);
        int i3 = bai2 - bai1;
        if (i3 > 2) {
            return false;
        }

        List<Integer> fuList = fu.stream().sorted().collect(Collectors.toList());
        Integer fu1 = fuList.get(0);
        Integer fu2 = fuList.get(collect.size() - 1);
        int i4 = fu2 - fu1;
        if (i4 > 2) {
            return false;
        }
        if (flag) {
            System.out.println("主：" + i2);
            System.out.println("白：" + i3);
            System.out.println("副：" + i4);
            System.out.println("夜：" + i1);
        }
        return true;
    }

    private static int getHoliday(int year, int month) {
        String str = "";
        try {
            String holidayUrl = URL + year + "-" + month;
            HttpRequest httpRequest = new HttpRequest(holidayUrl);
            HttpResponse httpResponse = httpRequest.execute();
            BufferedInputStream bis = new BufferedInputStream(httpResponse.bodyStream());
            InputStreamReader isr = new InputStreamReader(bis, StandardCharsets.UTF_8);
            StringBuilder sb = new StringBuilder();
            char[] buf = new char[40960];
            int len;
            while ((len = isr.read(buf)) != -1) {
                sb.append(buf, 0, len);
            }
            str = sb.toString();
        } catch (Exception ignored) {
            System.err.println("休假接口调用失败");
            System.exit(-1);
        }

        JSONObject holiday = JSONUtil.parseObj(str).getJSONObject("holiday");
        Set<String> strings = holiday.keySet();
        int count = 0;
        for (String key : strings) {
            Boolean holiday1 = holiday.getJSONObject(key).getBool("holiday");
            if (holiday1) {
                count++;
            }
        }
        return count;
    }


}
